#ifndef __LIB_H
#define __LIB_H

#define NULL 0

//ptr:结构体中member地址
//type:结构体类型
//member:结构体中的成员
//TODO 这里要调试一下，看看转成汇编后是怎样的
#define container_of(ptr,type,member)       \
({                                      \
        typeof(((type*)0)->member)* p = (ptr);      \
        (type*)((unsigned long)p - (unsigned long)&(((type*)0)->member));    \
})

#define sti()           __asm_volatile__ ("sti \n\t":::"memory")
#define cli()           __asm_volatile__ ("cli \n\t":::"memory")
#define nop()           __asm_volatile__ ("nop \n\t")
#define io_mfence()     __asm_volatile__ ("mfence \n\t":::"memory")

struct List{
    struct List* prev;
    struct List* next;
};

void list_init(struct List* list);
void list_add_to_behind(struct List* entry,struct List* newEntry);
void list_add_to_before(struct List* entry,struct List* newEntry);
void list_del(struct List* entry);
long list_is_empty(struct List* entry);
struct List* list_prev(struct List* entry);
struct List* list_next(struct List* entry);

void*   memcpy(void* from,void* to,long num);
int     memcmp(void* first,void* second,long count);
void*   memset(void* address,unsigned char c,long count);
void*   strcpy(char* dest,char* src);
char*   strncpy(char* dest,char* src,long count);
char*   strcat(char* dest,char* src);
int     strcmp(char* first,char* second);
int     strncmp(char* first,char* second,long count);
int     strlen(char* src);

inline unsigned long bit_set(unsigned long* addr,unsigned long nr){
    return *addr | (1UL << nr);
}

inline unsigned long bit_Get(unsigned long* addr,unsigned long nr){
    return *addr & (1UL << nr);
}

inline unsigned long bit_clean(unsigned long* addr,unsigned long nr){
    return  *addr & (~(1UL << nr));
}

//inb inw inl 对应读取1字节，2字节，4字节
//mfence 内存屏障
inline unsigned char io_in8(unsigned short port){
    unsigned char ret = 0;
    __asm__ __volatile__( "inb %%dx, %0 \n\t"
        "mfence \n\t"
        :"=a"(ret)
        :"d"(port)
        :"memory");
    return ret;
}

inline unsigned int io_in32(unsigned short port){
    unsigned int ret = 0;
    __asm__ __volatile__( "inl %%dx, %0 \n\t"
        "mfence \n\t"
        :"=a"(ret)
        :"d"(port)
        :"memory");
}

inline void io_out8(unsigned short port,unsigned char value){
    __asm__ __volatile__("outb %%al,%%dx  \n\t"
        "mfence     \n\t"
        :
        :"a"(value),"d"(port)
        :"memory");
}

inline void io_out32(unsigned short port,unsigned int value){
    __asm__ __volatile__("outl %%eax,%%dx  \n\t"
        "mfence     \n\t"
        :
        :"a"(value),"d"(port)
        :"memory");
}

#define port_insw(port,buffer,nr)	\
__asm__ __volatile__("cld;rep;insw;mfence;"::"d"(port),"D"(buffer),"c"(nr):"memory")

#define port_outsw(port,buffer,nr)	\
__asm__ __volatile__("cld;rep;outsw;mfence;"::"d"(port),"S"(buffer),"c"(nr):"memory")

#endif